import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import WipOrderReport from '@main/entities/service/admin/wip/wip-order-report.entity';
import ProductionOrder from '@main/entities/service/admin/production/production-order.entity';
// import { BaseMachineService } from './../../../admin/base/machine/machine.service';
import { Repository } from 'typeorm';
import { format } from 'date-fns';
import BaseMachine from '@main/entities/service/admin/base/base-machine.entity';
import BaseShift from '@main/entities/service/admin/base/base-shift.entity';
import WipShutdownList from '@main/entities/service/admin/wip/wip-shutdown-list.entity';

@Injectable()
export class ReportFormDailyProductionQuotaService {
  constructor(
    @InjectRepository(WipOrderReport)
    private orderReportRepository: Repository<WipOrderReport>,
    @InjectRepository(BaseMachine)
    private machineRepository: Repository<BaseMachine>,
    @InjectRepository(BaseShift) private shiftRepository: Repository<BaseShift>,
    @InjectRepository(ProductionOrder)
    private orderRepository: Repository<ProductionOrder>,
    @InjectRepository(WipShutdownList)
    private shutdownListRepository
  ) {}

  /**
   * 罗列所有配置
   */
  async page(data) {
    const { pageSize, pageNum, entity = {} } = data;

    const { reportTimeStartTime, reportTimeEndTime } = entity;

    // SELECT
    //     DATE(datetime(wor.report_time / 1000, 'unixepoch')) AS reportDate,  -- 将毫秒转换为秒后再进行日期转换
    //     wor.machine_code,
    //     wor.shift_code,
    //     GROUP_CONCAT(wor.report_code ORDER BY wor.report_time DESC) AS reportCodes  -- 合并 reportCode
    // FROM
    //     wip_order_report wor
    // JOIN
    //     production_order po ON wor.order_code = po.order_code  -- 连接 production_order 表
    // WHERE
    //     wor.report_finish_status = 1  -- reportStatus 为 1
    //     AND po.order_status_code = '40'  -- orderStatusCode 为 40
    //     AND wor.report_time BETWEEN strftime('%s', '2024-01-01 00:00:00') * 1000 AND strftime('%s', '2025-01-02 23:59:59') * 1000  -- 使用 strftime 转换为时间戳并乘以1000
    // GROUP BY
    //     reportDate, wor.machine_code, wor.shift_code  -- 按日期、机器编号和班组分组
    // ORDER BY
    //     reportDate DESC, wor.machine_code, wor.shift_code  -- 排序
    // LIMIT 10 OFFSET 0;  -- 分页

    const list = await this.orderReportRepository
      .createQueryBuilder('wor')
      .select([
        "DATE(datetime(wor.report_time / 1000, 'unixepoch')) AS reportDate",
        'wor.machine_code AS machineCode',
        'wor.shift_code AS shiftCode',
        'GROUP_CONCAT(wor.report_code ORDER BY wor.report_time DESC) AS reportCodes',
      ])
      .innerJoin(ProductionOrder, 'po', 'wor.order_code = po.order_code')
      .where('wor.report_finish_status = :status', { status: 1 })
      .andWhere('po.order_status_code = :orderStatusCode', { orderStatusCode: '40' })
      .andWhere(
        "wor.report_time BETWEEN strftime('%s', :startDate) * 1000 AND strftime('%s', :endDate) * 1000",
        {
          startDate: format(new Date(reportTimeStartTime), 'yyyy-MM-dd HH:mm:ss'),
          endDate: format(new Date(reportTimeEndTime), 'yyyy-MM-dd HH:mm:ss'),
        }
      )
      .groupBy('reportDate, wor.machine_code, wor.shift_code')
      .orderBy('reportDate', 'DESC')
      .addOrderBy('wor.machine_code')
      .addOrderBy('wor.shift_code')
      .skip((pageNum - 1) * pageSize)
      .take(pageSize)
      .getRawMany();

    const machineObj = {};

    const shiftObj = {};

    for (let i = 0; i < list.length; i++) {
      const { reportCodes, shiftCode, machineCode } = list[i];

      const reportCodeList = reportCodes.split(',');

      if (machineObj[machineCode]) {
        list[i].machineName = machineObj[machineCode].machineName;
      } else {
        const obj = await this.machineRepository.findOne({ where: { machineCode } });

        if (obj) {
          machineObj[machineCode] = obj;

          list[i].machineName = obj.machineName;
        }
      }

      if (shiftObj[shiftCode]) {
        list[i].shiftName = shiftObj[shiftCode].shiftName;
      } else {
        const obj = await this.shiftRepository.findOne({ where: { shiftCode } });

        if (obj) {
          shiftObj[shiftCode] = obj;

          list[i].shiftName = obj.shiftName;
        }
      }

      const orderList = [];

      let completedNum = 0; // 完工数量

      let goodNum = 0; // 良品数量

      let badNum = 0; // 不良品数量

      let goodArea = 0; // 良品面积(㎡)

      let debugTime = 0; // 调机用时

      let productTime = 0; // 生产用时

      let shutdownTime = 0; // 停机用时

      let electricityConsumption = 0; // 用电量(kW.h)

      let waterConsumption = 0; // 用水量(t)

      for (let j = 0; j < reportCodeList.length; j++) {
        const reportCode = reportCodeList[j];

        const obj = await this.orderReportRepository.findOne({ where: { reportCode } });

        if (obj) {
          const {
            orderCode,
            goodNum: gNum,
            badNum: bNum,
            reportTime,
            createTime,
            reportStatus,
            reportConfirmNum,
            reportNum,
            adjuestDuration,
            electricityConsumption: eNum,
            waterConsumption: wNum,
          } = obj;

          if (!orderList.includes(orderCode)) {
            orderList.push(orderCode);
          }

          if (reportStatus === 1) {
            completedNum += reportConfirmNum;
          } else {
            completedNum += reportNum;
          }

          goodNum += gNum;

          badNum += bNum;

          productTime += Number(
            ((new Date(reportTime).getTime() - new Date(createTime).getTime()) / 1000 / 60).toFixed(
              2
            )
          );

          if (adjuestDuration) {
            debugTime += adjuestDuration;
          }

          if (eNum) {
            electricityConsumption += eNum;
          }

          if (wNum) {
            waterConsumption += wNum;
          }

          const obj1 = await this.orderRepository.findOne({ where: { orderCode } });

          if (obj1) {
            const { paperLength, paperWidth, templateNum = 1 } = obj1;

            // 良品面积 =（纸板面积 / 模数）* 良品数

            // 纸板面积=根据工单对应的产品的纸板宽*长

            goodArea += ((paperLength * paperWidth) / (templateNum ? templateNum : 1)) * gNum;
          }
        }

        const shutdownList = await this.shutdownListRepository.find({ where: { reportCode } });

        for (let k = 0; k < shutdownList.length; k++) {
          const { shutdownDuration } = shutdownList[k];

          shutdownTime += shutdownDuration;
        }
      }

      const badRate = (badNum / completedNum).toFixed(2) + '%'; // 不良率

      const avgSpeed = Number((completedNum / productTime).toFixed(0)); // 平均速度

      list[i]['completedNum'] = completedNum;

      list[i]['completedOrders'] = orderList.length;

      list[i]['goodNum'] = goodNum;

      list[i]['badNum'] = badNum;

      list[i]['goodArea'] = goodArea.toFixed(4);

      list[i]['debugTime'] = debugTime.toFixed(2);

      list[i]['productTime'] = productTime;

      list[i]['shutdownTime'] = shutdownTime.toFixed(2);

      list[i]['electricityConsumption'] = electricityConsumption.toFixed(2);

      list[i]['waterConsumption'] = waterConsumption.toFixed(2);

      list[i]['badRate'] = badRate;

      list[i]['avgSpeed'] = avgSpeed;
    }

    const sql = `
      SELECT
      COUNT(*) AS total
      FROM
        (
            SELECT
                DATE(datetime(wor.report_time / 1000, 'unixepoch')) AS reportDate,
                wor.machine_code,
                wor.shift_code
            FROM
                wip_order_report wor
            JOIN
                production_order po ON wor.order_code = po.order_code
            WHERE
                wor.report_finish_status = 1
                AND po.order_status_code = '40'
                AND wor.report_time BETWEEN strftime('%s', '${format(
                  new Date(reportTimeStartTime),
                  'yyyy-MM-dd HH:mm:ss'
                )}') * 1000 AND strftime('%s', '${format(
      new Date(reportTimeEndTime),
      'yyyy-MM-dd HH:mm:ss'
    )}') * 1000
            GROUP BY
                reportDate, wor.machine_code, wor.shift_code
        ) AS grouped_data;
      `;

    const total = await this.orderReportRepository.query(sql);

    // const total = totalQuery ? totalQuery.total : 0;

    return [list, total[0]?.total ?? 0];

    // const results = await queryBuilder.getRawMany();

    // return results;

    // const [items, totalItems] = await this.orderReportRepository
    //   .createQueryBuilder('t')
    //   .select('FROM_UNIXTIME(t.report_time)', 'time')
    //   .addSelect('t.machine_code')
    //   .addSelect('t.shift_code')
    //   .addSelect('COUNT(t.id)', 'num')
    //   .addSelect('SUM(t.good_num)', 'goodNum')
    //   .addSelect('SUM(t.bad_num)', 'badNum')
    //   .addSelect('COUNT(DISTINCT o.order_code)', 'orderCount')
    //   .from(WipOrderReport, 't')
    //   .leftJoin(ProductionOrder, 'o', 't.order_code = o.order_code') // 添加内连接
    //   .where('t.report_finish_status = :reportFinishStatus', { reportFinishStatus: 1 })
    //   .andWhere('o.order_status_code = :orderStatusCode', { orderStatusCode: '40' })
    //   .groupBy('time')
    //   .addGroupBy('t.machine_code')
    //   .addGroupBy('t.shift_code')
    //   .skip((pageNum - 1) * pageSize)
    //   .take(pageSize)
    //   .getRawMany();

    // const machineList: any = await this.baseMachineService.page({
    //   pageNum,
    //   pageSize,
    //   entity: {
    //     machineName: '',
    //     machineCode: '',
    //   },
    // });

    // const { reportTimeStartTime, reportTimeEndTime } = entity;

    // const where = {};

    // if (reportTimeStartTime && reportTimeEndTime) {
    //   where['reportTime'] = Between(reportTimeStartTime, reportTimeEndTime);
    // }

    // for (let i = 0; i < machineList.length; i++) {
    //   const list = await this.orderReportRepository.find({
    //     where: {
    //       ...where,
    //       machineCode: machineList[i].machineCode,
    //     },
    //   });
    // }

    // const [list, total] = await this.orderReportRepository.findAndCount({
    //   where,
    //   order: {
    //     updateTime: 'DESC',
    //   },
    //   take: pageSize,
    //   skip: (pageNum - 1) * pageSize,
    // });

    // return [list, total];
  }
}
